# append、insert等等加入的必须是节点，push可以将值直接转化节点加入，相应的pop出来也是节点，rol_pop是循环版本的pop
# 循环版本是有周期的插入/推出，如：1，2，3，周期是3，rol_pop(4)将相当于pop(1)，而pop(4)则是pop(len(self))，因为4大于周期
# link方法将一个可迭代对象连为环链，to_list相当于link的反向操作
# 有一些高级方法未实现
# rotate(n)方法将环链旋转，n默认为1，即逆时针旋转1位，reverse方法将头尾指针反转
# 直接运行文件是一个内置环链方法的拼夕夕版Shell，，，可以方便调教环链
from functools import cached_property


class Node:
    def __init__(self, val):
        self.val = val
        self.next = None

    def __eq__(self, node):
        return self.val == node.val

    def __lt__(self, node):
        return self.val < node.val

    def __str__(self):
        return f' {self.val}\n <class {__name__}.Node> dtype=' + \
               f'{type(self.val)}'.strip('<class=>').replace('\'', '')


class RolLink:
    def __init__(self):
        self.__head = None
        self.__tail = None

    def __len__(self):
        return self.__get_length

    def __str__(self):
        return f'<-{[i for i in self]}->'  # TODO

    def __add__(self, obj):
        pass

    def __mul__(self, obj):
        pass

    def __contains__(self, val):
        for i in self:
            if val == i:
                return True
        return False

    def __getitem__(self, item):
        pass

    def __setitem__(self, key, value):
        pass

    def __delitem__(self, key):
        pass

    def __iter__(self):
        self.iterator = self.__head
        self.is_begin = True
        return self

    def __next__(self):
        if not self.iterator:
            raise StopIteration
        if self.iterator is not self.__head or self.is_begin:
            self.is_begin = False
            return_item = self.iterator.val
            self.iterator = self.iterator.next
            return return_item
        else:
            raise StopIteration

    @cached_property
    def __get_length(self):
        if '__get_length' in dir(self):
            return self.__get_length
        if self.is_empty():
            return 0
        counter = 0
        curr_node = self.__head
        while curr_node.next is not self.__head:
            curr_node = curr_node.next
            counter += 1
        return counter

    def is_empty(self):
        return not bool(self.__head)

    def append(self, node):
        if self.is_empty():
            self.__head = self.__tail = node
        else:
            self.__tail.next = node
        node.next = self.__head
        self.__tail = self.__tail.next
        self.__get_length += 1

    def insert(self, index, node):
        if self.is_empty():
            self.__head = self.__tail = node
            self.__tail.next = self.__head
        else:
            if index < 0:
                index = self.__get_length + index
            if index <= 0:
                node.next = self.__head
                self.__tail.next, self.__head = [node]*2
            elif index >= self.__get_length:
                node.next = self.__head
                self.__tail.next = node
                self.__tail = self.__tail.next
            else:
                temp_curr = 1
                curr_node = self.__head
                while temp_curr < index:
                    curr_node = curr_node.next
                    temp_curr += 1
                node.next = curr_node.next
                curr_node.next = node
        self.__get_length += 1

    def rol_insert(self, index, node):
        """ 按周期循环插入 """
        while index < 0:
            index += self.__get_length
        while index >= self.__get_length:
            index -= self.__get_length
        self.insert(index, node)

    def push(self, val):
        """ 将值推入链表 """
        self.append(Node(val))

    def pop(self, index=-1):
        if self.is_empty():
            raise IndexError('pop from empty rolLink')
        if index < 0:
            index = self.__get_length + index
        if index <= 0:
            temp = popitem = self.__head
            while temp.next is not popitem:
                temp = temp.next
            self.__tail = temp
            self.__tail.next, self.__head = [self.__head.next]*2
            if popitem is self.__head:
                self.__head = self.__tail = None
        elif index >= self.__get_length-1:
            temp = self.__head
            popitem = self.__tail
            while temp.next.next is not self.__head:
                temp = temp.next
            temp.next = self.__head
            self.__tail = temp
        else:
            temp_curr = 1
            curr_node = self.__head
            while temp_curr < index:
                curr_node = curr_node.next
                temp_curr += 1
            popitem = curr_node.next
            curr_node.next = curr_node.next.next
        self.__get_length -= 1
        popitem.next = None
        return popitem

    def rotate(self, n=1):
        if self.is_empty():
            return
        while n < 0:
            n += self.__get_length
        while n >= self.__get_length and n:
            n -= self.__get_length
        for i in range(n):
            self.insert(0, self.pop(-1))

    def reverse(self):
        self.__head, self.__tail = self.__tail, self.__head

    def rol_pop(self, index):
        """ 按周期循环推出 """
        if self.is_empty():
            index = 0
        else:
            while index < 0:
                index += self.__get_length
            while index >= self.__get_length:
                index -= self.__get_length
        self.pop(index)

    def clear(self):
        self.__head = self.__tail = None
        self.__get_length = 0

    def link(self, iterable):
        """ 链接迭代器值末尾 """
        for i in iterable:
            if isinstance(i, Node):
                self.append(i)
            else:
                self.push(i)

    def to_list(self, rol=1):
        res = list()
        for i in self:
            res.append(i.val)
        return res*rol


def link(iterable):
    result = RolLink()
    for i in iterable:
        if isinstance(i, Node):
            result.append(i)
        else:
            result.push(i)
    return result


if __name__ == '__main__':
    import sys

    print(f'Python {sys.version} on {sys.platform}')
    print('Type "help", "copyright", "credits" or "license" for more information.')
    while True:
        try:
            order = input('>>> ')
            if 'while' in order or 'for' in order or 'def' in order \
                    or 'class' in order or 'try' in order or 'match' in order:
                order += '\n'
                temp = input('... ')
                temp.replace('\t', '    ')
                while temp:
                    order += temp
                    temp = input('... ')
            try:
                exec(f"if (temp:={order}) is not None:print(temp)")
            except Exception as _:
                exec(order)
        except Exception as error:
            print(type(error), error, sep='\n    ')
